package chapter_3.demo7;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @author: hero生仔
 */
public class Solution {
    public static void main(String[] args) {
        extracted();

        extracted1();

        extracted2();

        Fruit apple = givenFruit("apple", 120);
        System.out.println(apple);

        Fruit orange = givenFruit("orange", 130);
        System.out.println(orange);


        /**
         * 构造函数引用的语法是ClassName::new。假如说一个三个构造函数的类怎么办呢？比如说 Color(int ,int ,int)，那么如何使用构造函数呢？
         * 这种没有定义的，就需要自定义了：
         * public interface TriFunction<T , U, V, R> {
         *     R apply(T t, U u, V v);
         * }
         */
    }
    static Map<String ,Function<Integer,Fruit>> map = new HashMap<>();
    static {
        map.put("apple",Apple::new);
        map.put("orange",Orange::new);
    }

    public static Fruit givenFruit(String fruit,Integer weight) {
        // 可以使用 Map 来将构造函数映射到字符串值。可以创建一个 givenFruit 方法，给他一个String 和一个 Integer，就可以创建出不同重量的各种水果
        return map.get(fruit)
                .apply(weight);
    }
    private static void extracted2() {
        // 如果你有一个具有两个参数的构造函数Apple(String color, Integer weight)，那么它就适合BiFunction接口的签名
        BiFunction<String, Integer, Apple> c3 = Apple::new;
        Apple apple01 = c3.apply("green", 100);
        System.out.println(apple01.hashCode());

        // 等价于
        BiFunction<String, Integer, Apple> c4 = (String s, Integer i) -> new Apple();
        Apple apple02 = c4.apply("green", 100);
        System.out.println(apple02.hashCode());
    }

    private static void extracted1() {
        // 一个由Integer构成的List中的每个元素都通过我们前面定义的类似的map方法传递给了Apple的构造函数，得到了一个具有不同重量苹果的List
        List<Integer> list = Arrays.asList(7, 3, 4, 10);
        List<Apple> result = map(list, Apple::new);
        System.out.println(result);
    }

    public static List<Apple> map(List<Integer> list, Function<Integer, Apple> f) {
        ArrayList<Apple> result = new ArrayList<>();
        for (Integer i : list) {
            result.add(f.apply(i));
        }
        return result;
    }

    private static void extracted() {
        /**
         * 假设有一个构造函数没有参数 他适合 Supplier 的签名 () -> Apple
         */
        // 构造函数的引用
        Supplier<Apple> c1 = Apple::new;
        Apple apple01 = c1.get();
        System.out.println(apple01.hashCode());

        // 等价于
        Supplier<Apple> c2 = () -> new Apple();
        Apple apple02 = c2.get();
        System.out.println(apple02.hashCode());

        /**
         * 假设构造函数的签名是 Apple(Integer weight)，那么它就适合 Function 接口的签名，
         */
        Function<Integer, Apple> c4 = Apple::new;
        Apple apple04 = c4.apply(100);
        System.out.println(apple04.hashCode());

        // 等价于
        Function<Integer, Apple> c3 = (Integer i) -> new Apple(i);
        Apple apple03 = c3.apply(100);
        System.out.println(apple03.hashCode());
    }
}
